/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.wsonrpc.core;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 */
class WsonrpcCallbackCache {

    private final Map<String, CallbackWeakReference> map = new ConcurrentHashMap<>();
    private final ReferenceQueue<WsonrpcCallback> queue = new ReferenceQueue<>();

    void put(String requestId, WsonrpcCallback callback) {
        processQueue();
        map.put(requestId, new CallbackWeakReference(requestId, callback, queue));
    }

    WsonrpcCallback out(String requestId) {
        processQueue();
        CallbackWeakReference ref = map.remove(requestId);
        if (ref != null) {
            return ref.get();
        }
        return null;
    }

    private void processQueue() {
        CallbackWeakReference ref;
        while ((ref = (CallbackWeakReference) queue.poll()) != null) {
            map.remove(ref.requestId);
        }
    }

    /**
     *
     * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
     */
    private static class CallbackWeakReference extends WeakReference<WsonrpcCallback> {

        private final String requestId;

        CallbackWeakReference(String requestId, WsonrpcCallback referent, ReferenceQueue<? super WsonrpcCallback> q) {
            super(referent, q);
            this.requestId = requestId;
        }
    }

}
